<?php

namespace libs\qoy;
use libs\qoy\Exception\ExceptionInternalServerError;
use libs\qoy\Filter\IFilter;
/**
 * 基础接口实现型
 */
class BaseController {
    /**
     * 程序注入接口
     * @var DI;
     */
    protected $di;

    public function __construct() {
        $this->di= DI::instance();
    }
    /**
     * 设置规则解析后的接口参数
     * @param string $name 接口参数名字
     * @param mixed $value 接口参数解析后的值
     */
    public function __set($name, $value) {
       
        $this->$name = $value;
        
    }
    /**
     * 获取规则解析后的接口参数
     * @param string $name 接口参数名字
     * @throws ExceptionInternalServerError 获取未设置的接口参数时，返回500
     * @return mixed
     */
    public function __get($name) {
        if(!isset($this->$name) || empty($name)) {
            throw new ExceptionInternalServerError(
                ExceptionInternalServerError::KEY_UNDEFINED, $name
            );
        }
        return $this->$name;
    }

    /**
     * 初始化
     *
     * 主要完成的初始化工作有：
     * - 1、[必须]按参数规则解析生成接口参数
     * - 2、[可选]过滤器调用，如：签名验证
     * - 3、[可选]用户身份验证
     *
     * @uses BaseController::createMemberValue() 
     * @uses BaseController::filterCheck()
     * @return null
     */
    public function init() {
        $this->createMemberValue();
        $this->filterCheck();
    }

    /**
     * 按参数规则解析生成接口参数
     *
     * 根据配置的参数规则，解析过滤，并将接口参数存放于类成员变量
     * 
     * @uses BaseController::getApiRules()
     */
    protected function createMemberValue() {
        foreach ($this->getApiRules() as $key => $rule) {
            
            $this->$key = Request::getByRule($rule);
        }
    }

    /**
     * 取接口参数规则
     *
     * 主要包括有：
     * - 1、[固定]系统级的service参数
     * - 2、应用级统一接口参数规则，在app.apiCommonRules中配置
     * - 3、接口级通常参数规则，在子类的*中配置
     * - 4、接口级当前操作参数规则
     *
     * <b>当规则有冲突时，以后面为准。另外，被请求的函数名和配置的下标都转成小写再进行匹配。</b>
     *
     * @uses BaseController::getRules()
     * @return array
     */
    public function getApiRules() {
        $rules = array();

        $allRules = $this->getRules();
        if (!is_array($allRules)) {
            $allRules = array();
        }

        $allRules = array_change_key_case($allRules, CASE_LOWER);
        $action = strtolower(Request::getAction()); 
        if (isset($allRules[$action]) && is_array($allRules[$action])) {
            $rules = $allRules[$action];
        }
        if (isset($allRules['*'])) {
            $rules = array_merge($allRules['*'], $rules);
        }
        
        $apiCommonRules = $this->di->config->get('app.apiCommonRules', array());
        if (!empty($apiCommonRules) && is_array($apiCommonRules)) {
            $rules = array_merge($apiCommonRules, $rules);
        }

        return $rules;
    }

    /**
     * 获取参数设置的规则
     *
     * 可由开发人员根据需要重载
     * 
     * @return array
     */
    public function getRules() {
        return [];
    }

    /**
     * 过滤器调用
     *
     * 可由开发人员根据需要重载，以实现项目拦截处理，需要：
     * - 1、实现IFilter::check()接口
     * - 2、注册的过滤器到DI()->filter
     * @see  IFilter::check()
     * @throws ExceptionBadRequest 当验证失败时，请抛出此异常，以返回400
     */
    protected function filterCheck() {
        $filter = $this->di->filter;
        if (isset($filter)) {
            if (!($filter instanceof IFilter)) {
                throw new ExceptionInternalServerError(ExceptionInternalServerError::FILTER);
            }
            $filter->check();
        }
    }

}
